package dream

import (
	"sync"
	"sync/atomic"
)

type sAsync2RunAble struct {
	timeout  int32
	ch_event chan func()
	stoped   int32
	count    uint32
	name     string
}

func (p *sAsync2RunAble) doFunc(f func()) {
	f()
}
func (p *sAsync2RunAble) RunFunc(f func()) {
	if atomic.CompareAndSwapInt32(&p.stoped, 0, 0) {
		p.ch_event <- f
	}
}
func (p *sAsync2RunAble) Stop() {
	atomic.StoreInt32(&p.stoped, 1)
	for i := uint32(0); i < p.count; i++ {
		p.ch_event <- nil
	}
	close(p.ch_event)
}

func NewAsyncMultiRun(n string, cnt uint32) IRunCtrl1 {
	p := &sAsync2RunAble{
		timeout:  1000,
		ch_event: make(chan func(), 1024*10),
		stoped:   0,
		count:    cnt,
		name:     n,
	}
	return p
}

func (p *sAsync2RunAble) Run(wg *sync.WaitGroup) {
	if wg != nil {
		wg.Add(int(p.count))
	}
	for i := uint32(0); i < p.count; i++ {
		go p.run(i, wg)
	}
}

func (p *sAsync2RunAble) run(index uint32, wg *sync.WaitGroup) {
	defer func() { CrashSnap(recover()) }()
	Logi(LOG_KERL, "MultiRun ", p.name, "(", index, ") run ...")
	for {
		f := <-p.ch_event
		if f == nil {
			break
		} else {
			f()
		}
	}
	Logi(LOG_KERL, " ...MultiRun ", p.name, "(", index, ") exit")
	if wg != nil {
		wg.Done()
	}
}
